/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ecom.ejb;

import ecom.entity.AccountRemote;
import ecom.entity.Commande;
import ecom.entity.CommandeRemote;
import ecom.entity.Ligne;
import ecom.entity.LigneRemote;
import ecom.entity.Product;
import ecom.entity.ProductRemote;
import exceptions.CartException;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.ejb.Local;
import javax.ejb.Stateful;

/**
 *
 * @author François
 */
@Stateful
@Local(CartLocal.class)
public class Cart implements CartLocal {

    private Set<LigneRemote> lignes;

    private double montant;

    private StatutCart statut = StatutCart.EMPTY;

    @Override
    public void addProduit(ProductRemote product, int quantite)
	    throws CartException {
	Ligne ligne = null;
	boolean trouve = false;

	if (StatutCart.BOUGHT.equals(this.statut)) {
	    throw new CartException(
		    "Impossible d'ajouter un produit une fois que le caddie a été acheté");
	}

	if (this.lignes != null) {
	    Iterator<LigneRemote> it = this.lignes.iterator();

	    while (it.hasNext() && !trouve) {
		ligne = (Ligne) it.next();

		if (product.equals(ligne.getProduct())) {
		    trouve = true;

		    ligne.addQuantite(quantite);
		}
	    }
	} else {
	    this.lignes = new HashSet<LigneRemote>();
	    this.statut = StatutCart.EMPTY;
	}

	if (!trouve) {
	    ligne = new Ligne();
	    ligne.setProduct((Product) product);
	    ligne.setQuantite(quantite);
	    this.lignes.add(ligne);

	    this.statut = StatutCart.FILLING;
	}

	this.calculerMontant();
    }

    @Override
    public void removeProduit(ProductRemote product, int quantite)
	    throws CartException {
	if (StatutCart.BOUGHT.equals(this.statut)) {
	    throw new CartException(
		    "Impossible de retirer un produit une fois que le caddie a été acheté");
	}

	boolean trouve = false;
	if (this.lignes != null) {

	    Iterator<LigneRemote> it = this.lignes.iterator();
	    LigneRemote ligne = null;

	    while (it.hasNext() && !trouve) {
		ligne = it.next();

		if (ligne.getProduct().equals(product)) {
		    trouve = true;

		    if (ligne.getQuantite() - quantite <= 0) {
			this.lignes.remove(ligne);
		    } else {
			ligne.removeQuantite(quantite);
		    }
		}
	    }

	    if (trouve) {
		this.calculerMontant();
	    }
	}

	if (!trouve) {
	    throw new CartException(
		    "Oops! Le produit n'est pas dans le caddie");
	}
    }

    @Override
    public CommandeRemote buy(AccountRemote compte) throws CartException {

	Commande retour = null;

	if (StatutCart.EMPTY.equals(this.statut)) {
	    throw new CartException("Impossible d'acheter un caddie vide");
	}
	if (compte.getSolde() < this.getMontant()) {
	    throw new CartException(
		    "Le solde du compte est insuffisant pour le montant du caddie");
	}

	retour = new Commande(null, new Date(), this.getMontant(), compte,
		this.getLignes());

	Iterator<LigneRemote> it = retour.getLignes().iterator();
	LigneRemote ligne = null;

	while (it.hasNext()) {
	    ligne = (LigneRemote) it.next();
	    ligne.setCommande(retour);
	}

	return retour;
    }

    @Override
    public void cancel() {
	this.lignes = new HashSet<LigneRemote>();
	this.statut = StatutCart.EMPTY;
	this.calculerMontant();
    }

    @Override
    public Set<LigneRemote> getProduits() {
	return this.getLignes();
    }

    public Set<LigneRemote> getLignes() {
	return this.lignes;
    }

    public void setLignes(Set<LigneRemote> lignes) {
	this.lignes = lignes;
    }

    @Override
    public double getMontant() {
	return this.montant;
    }

    public void setMontant(double montant) {
	this.montant = montant;
    }

    public StatutCart getStatut() {
	return this.statut;
    }

    @Override
    public void setStatut(StatutCart statut) {
	this.statut = statut;
    }

    private void calculerMontant() {
	this.montant = 0.0;

	Iterator<LigneRemote> it = this.lignes.iterator();
	LigneRemote ligne = null;

	while (it.hasNext()) {
	    ligne = (LigneRemote) it.next();

	    this.montant += ligne.getMontant();
	}
    }

    @Override
    public int hashCode() {
	int prime = 31;
	int result = 1;
	result = prime * result + ((lignes == null) ? 0 : lignes.hashCode());
	long temp;
	temp = Double.doubleToLongBits(montant);
	result = prime * result + (int) (temp ^ (temp >>> 32));
	return result;
    }

    @Override
    public boolean equals(Object obj) {
	if (this == obj) {
	    return true;
	}
	if (obj == null) {
	    return false;
	}
	if (!(obj instanceof Cart)) {
	    return false;
	}
	Cart other = (Cart) obj;
	if (lignes == null) {
	    if (other.lignes != null) {
		return false;
	    }
	} else if (!lignes.equals(other.lignes)) {
	    return false;
	}
	if (Double.doubleToLongBits(montant) != Double
		.doubleToLongBits(other.montant)) {
	    return false;
	}
	return true;
    }

    @Override
    public String toString() {
	return "Caddie [lignes=" + lignes + ", montant=" + montant + "]";
    }
}